[网络流24题]试题库问题

2020-02-01
网络流24题

题意

每一道题目可以属于不同知识点(只能选择一个),选出$m$道题目组成试卷,使得每个知识点都恰好达到要求的题目数,求一组方案

题解

网络流建两层的图,最后看中间边的流量

调试记录

没有判last!=0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
const int maxn = 2e4 + 5;
const int S = 0;
const int T = 20004;
const int INF = 0x3f3f3f3f;
using namespace std;
struct E{
int to, nxt, f;
}e[maxn << 1]; int head[maxn], tot = 1;
void addedge(int u, int v, int f){
e[++tot].to = v, e[tot].nxt = head[u], e[tot].f = f;
head[u] = tot;
}
void ins(int u, int v, int f){
addedge(u, v, f); addedge(v, u, 0);
}
int dep[maxn];
bool bfs(){
queue <int> q; while (!q.empty()) q.pop(); q.push(S);
memset(dep, 0, sizeof dep); dep[S] = 1;
while (!q.empty()){
int cur = q.front(); q.pop();
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (e[i].f > 0 && dep[v] == 0){
dep[v] = dep[cur] + 1; q.push(v);
}
}
}
return dep[T] > 0;
}
int dfs(int cur, int Max){
if (cur == T) return Max;
int flow = 0;
for (int i = head[cur]; i; i = e[i].nxt){
int v = e[i].to;
if (flow == Max) return flow;
if (e[i].f > 0 && dep[v] == dep[cur] + 1){
int tmp = dfs(v, min(Max - flow, e[i].f));
flow += tmp;
e[i].f -= tmp;
e[i ^ 1].f += tmp;
}
}
return flow;
}
int maxflow = 0;
void Dinic(){
while (bfs())
maxflow += dfs(S, INF);
}
int k, n, last[2005][25], H = 0;
int main(){
// freopen("2.in", "r", stdin);
scanf("%d%d", &k, &n);
for (int h, i = 1; i <= k; i++){
scanf("%d", &h);
ins(i + n, T, h); H += h;
}
for (int m, i = 1; i <= n; i++){
ins(S, i, 1);
scanf("%d", &m);
for (int v, j = 1; j <= m; j++){
scanf("%d", &v); ins(i, v + n, 1); last[i][v] = tot - 1;
}
}
Dinic();
if (maxflow < H) puts("No Solution!");
else{
// printf("flow = %d\n", maxflow);
for (int i = 1; i <= k; i++){
printf("%d:", i);
for (int j = 1; j <= n; j++)
if (e[last[j][i]].f == 0 && last[j][i] != 0) printf(" %d", j);
puts("");
}
}
return 0;
}